"""
日志装饰器模块

提供各种日志装饰器，用于自动记录函数调用、性能监控、错误处理等
"""

import functools
import time
import traceback
from typing import Any, Callable, Optional, Union, List
from contextlib import contextmanager

from .logger import get_logger


def log_function_call(
    level: str = "INFO",
    include_args: bool = True,
    include_result: bool = True,
    max_arg_length: int = 100,
    logger_name: Optional[str] = None
):
    """
    记录函数调用的装饰器
    
    Args:
        level: 日志级别
        include_args: 是否记录参数
        include_result: 是否记录返回值
        max_arg_length: 参数字符串最大长度
        logger_name: 日志记录器名称
    """
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            logger = get_logger(logger_name or func.__module__)
            log_level = getattr(logger, level.lower())
            
            # 记录函数开始调用
            func_name = f"{func.__module__}.{func.__name__}"
            
            if include_args:
                args_str = _format_args(args, kwargs, max_arg_length)
                log_level(f"调用函数 {func_name} 开始，参数: {args_str}")
            else:
                log_level(f"调用函数 {func_name} 开始")
            
            try:
                result = func(*args, **kwargs)
                
                if include_result:
                    result_str = _format_value(result, max_arg_length)
                    log_level(f"函数 {func_name} 执行成功，返回值: {result_str}")
                else:
                    log_level(f"函数 {func_name} 执行成功")
                
                return result
                
            except Exception as e:
                logger.error(f"函数 {func_name} 执行失败: {str(e)}")
                raise
                
        return wrapper
    return decorator


def log_performance(
    threshold_ms: float = 1000.0,
    level: str = "INFO",
    slow_level: str = "WARNING",
    logger_name: Optional[str] = None
):
    """
    性能监控装饰器
    
    Args:
        threshold_ms: 慢查询阈值（毫秒）
        level: 正常日志级别
        slow_level: 慢查询日志级别
        logger_name: 日志记录器名称
    """
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            logger = get_logger(logger_name or func.__module__)
            func_name = f"{func.__module__}.{func.__name__}"
            
            start_time = time.time()
            try:
                result = func(*args, **kwargs)
                execution_time = (time.time() - start_time) * 1000
                
                if execution_time > threshold_ms:
                    getattr(logger, slow_level.lower())(
                        f"函数 {func_name} 执行较慢: {execution_time:.2f}ms"
                    )
                else:
                    getattr(logger, level.lower())(
                        f"函数 {func_name} 执行完成: {execution_time:.2f}ms"
                    )
                
                return result
                
            except Exception as e:
                execution_time = (time.time() - start_time) * 1000
                logger.error(
                    f"函数 {func_name} 执行失败 ({execution_time:.2f}ms): {str(e)}"
                )
                raise
                
        return wrapper
    return decorator


def log_errors(
    level: str = "ERROR",
    reraise: bool = True,
    include_traceback: bool = True,
    logger_name: Optional[str] = None
):
    """
    错误处理装饰器
    
    Args:
        level: 日志级别
        reraise: 是否重新抛出异常
        include_traceback: 是否包含堆栈跟踪
        logger_name: 日志记录器名称
    """
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            logger = get_logger(logger_name or func.__module__)
            func_name = f"{func.__module__}.{func.__name__}"
            
            try:
                return func(*args, **kwargs)
            except Exception as e:
                error_msg = f"函数 {func_name} 发生错误: {str(e)}"
                
                if include_traceback:
                    error_msg += f"\n堆栈跟踪:\n{traceback.format_exc()}"
                
                getattr(logger, level.lower())(error_msg)
                
                if reraise:
                    raise
                return None
                
        return wrapper
    return decorator


def log_step(
    step_name: Optional[str] = None,
    level: str = "INFO",
    logger_name: Optional[str] = None
):
    """
    操作步骤追踪装饰器
    
    Args:
        step_name: 步骤名称，默认使用函数名
        level: 日志级别
        logger_name: 日志记录器名称
    """
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            logger = get_logger(logger_name or func.__module__)
            name = step_name or func.__name__
            log_level = getattr(logger, level.lower())
            
            log_level(f"步骤开始: {name}")
            
            try:
                result = func(*args, **kwargs)
                log_level(f"步骤完成: {name}")
                return result
            except Exception as e:
                logger.error(f"步骤失败: {name} - {str(e)}")
                raise
                
        return wrapper
    return decorator


def retry_with_log(
    max_attempts: int = 3,
    delay: float = 1.0,
    backoff: float = 2.0,
    exceptions: Union[Exception, tuple] = Exception,
    logger_name: Optional[str] = None
):
    """
    带日志的重试装饰器
    
    Args:
        max_attempts: 最大重试次数
        delay: 初始延迟时间（秒）
        backoff: 延迟倍数
        exceptions: 需要重试的异常类型
        logger_name: 日志记录器名称
    """
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            logger = get_logger(logger_name or func.__module__)
            func_name = f"{func.__module__}.{func.__name__}"
            
            current_delay = delay
            
            for attempt in range(max_attempts):
                try:
                    if attempt > 0:
                        logger.info(f"重试函数 {func_name}，第 {attempt + 1} 次尝试")
                    
                    return func(*args, **kwargs)
                    
                except exceptions as e:
                    if attempt == max_attempts - 1:
                        logger.error(f"函数 {func_name} 重试 {max_attempts} 次后仍然失败: {str(e)}")
                        raise
                    
                    logger.warning(
                        f"函数 {func_name} 第 {attempt + 1} 次尝试失败: {str(e)}，"
                        f"{current_delay:.1f}秒后重试"
                    )
                    
                    time.sleep(current_delay)
                    current_delay *= backoff
                    
        return wrapper
    return decorator


@contextmanager
def log_context(
    context_name: str,
    level: str = "INFO",
    logger_name: Optional[str] = None
):
    """
    上下文管理器，用于记录代码块的执行
    
    Args:
        context_name: 上下文名称
        level: 日志级别
        logger_name: 日志记录器名称
    """
    logger = get_logger(logger_name)
    log_level = getattr(logger, level.lower())
    
    log_level(f"进入上下文: {context_name}")
    start_time = time.time()
    
    try:
        yield
        execution_time = (time.time() - start_time) * 1000
        log_level(f"退出上下文: {context_name} ({execution_time:.2f}ms)")
    except Exception as e:
        execution_time = (time.time() - start_time) * 1000
        logger.error(f"上下文异常: {context_name} ({execution_time:.2f}ms) - {str(e)}")
        raise


def _format_args(args: tuple, kwargs: dict, max_length: int) -> str:
    """格式化函数参数"""
    parts = []
    
    # 位置参数
    for arg in args:
        parts.append(_format_value(arg, max_length // 2))
    
    # 关键字参数
    for key, value in kwargs.items():
        parts.append(f"{key}={_format_value(value, max_length // 2)}")
    
    result = ", ".join(parts)
    if len(result) > max_length:
        result = result[:max_length - 3] + "..."
    
    return result


def _format_value(value: Any, max_length: int) -> str:
    """格式化值"""
    try:
        str_value = str(value)
        if len(str_value) > max_length:
            return str_value[:max_length - 3] + "..."
        return str_value
    except Exception:
        return "<无法序列化>"


# 便捷的装饰器别名
log_call = log_function_call()
log_perf = log_performance()
log_error = log_errors()
track_step = log_step()